# -*- coding: utf-8 -*-
# =============================================================================
#         Desc: 格式化MySQL通用日志并统计SQL执行频率
#       Author: GGA
#        Email:
#     HomePage:
#      Version: 1.0.0
#   LastChange: 2020-12-20
#      History:
# =============================================================================
import re
import hashlib
from utils.logger_helper import LoggerHelper

logger = LoggerHelper.get_logger()


class SQLFingerPrint(object):
    SQL_PATTERNS = [
        r"'(''|\\\\|\\'|[^'])*'",
        r'"(""|\\\\|\\"|[^"])*"',
        r'(""|".*?[^\\]")',
        r'(?![_A-ZÀ-Ü])-?\d+(?![_A-ZÀ-Ü])',
        r'(?![_A-ZÀ-Ü])-?(\d+(\.\d*)|\.\d+)(?![_A-ZÀ-Ü])',
        r'-?\d+(\.\d+)?E-?\d+',
        r'-?0x[\dA-F]+',
    ]

    @classmethod
    def format_sql(cls, sql: str):
        """
        替换掉多个空格、换行、制表符
        :param sql:
        :return:
        """
        new_sql = sql.replace("\r", " ").replace("\n", " ").replace("\t", " ") \
            .replace("(", " ( ").replace(")", " ) ").replace(",", " , ") \
            .replace(" " * 4, " ").replace(" " * 3, " ").replace(" " * 3, " ") \
            .replace(" " * 2, " ").replace(" " * 2, " ").strip()
        return new_sql

    @classmethod
    def get_finger_print(cls, sql: str):
        tmp_sql = cls.format_sql(sql=sql).strip()
        tmp_sql = tmp_sql.replace("\\\\", "")
        for item in cls.SQL_PATTERNS:
            # 开始尝试替换匹配字符为？
            tmp_sql = re.sub(item, " '?' ", tmp_sql, count=32)
        # 开始尝试替换数字
        tmp_sql = re.sub(r'\d+(?:\.\d+)?', "?", tmp_sql, count=1024)
        # 开始尝试替换多个空格
        tmp_sql = re.sub(r"\s+", " ", tmp_sql, count=1024)
        # 开始尝试替换多个问号
        tmp_sql = re.sub(r"( \? ,)+", " ? ,", tmp_sql, count=1024)
        if tmp_sql.count("'") % 2 == 1:
            tmp_sql = cls.get_finger_print(tmp_sql + "'")
        if tmp_sql.count('"') % 2 == 1:
            tmp_sql = cls.get_finger_print(tmp_sql + '"')
        return tmp_sql

    @classmethod
    def get_sql_md5(cls, sql: str):
        return hashlib.md5(sql.encode(encoding='UTF-8')).hexdigest()
